iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0
Modern Web

你知道這是什麼嗎? Chrome Extension MV3 With Vite系列 第 8

你知道這是什麼嗎? Chrome extension MV3 With Vite - Day8 Service Worker 訂閱推播

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20220908/201396360rzpmj8ghI.jpg

Hi Dai Gei Ho~ 我是Winnie ~ 同樣地延續Service Worker的主題(是SW系列的最後一篇了),今天我們要來實作 service worker 另一個常見功能 訂閱推播,帶大家了解下其中的運作原理。

訂閱推播 是什麼?

簡單來說就是 使用者在訂閱相關網站後,網站可以透過需求傳遞通知訊息給已訂閱的使用者。

而在 訂閱推播 功能中,主要可以分為 推送(Push) 與 通知(notification)

註冊Service Worker,透過 getSubscription 來

首先,開始在 Browser 中註冊一個 Service Worker,且回傳一個Promise,如果成功的話就會回傳一個ServiceWorkerRegistration參數,接著透過 pushManager方法來調用 getSubscription 判斷是否已經訂閱。

範例中回傳參數 swReg 即為 ServiceWorkerRegistration


if ('serviceWorker' in navigator && 'PushManager' in window) {
  // sw register
  navigator.serviceWorker.register('/sw.js', {
      scope: '/'
    })
    .then((swReg) => {
      swReg.pushManager.getSubscription().then(subscription => {
            // 使用者沒有訂閱
            if (!subscription) {
                subscribeUser(swReg);
            } else {
                console.log("You have subscribed our notification");
            }       
        });  
    })
    
} else {
  console.log('Push message is not Supported');
}

如果未訂閱,此時會觸發.pushManager.subscribe方法來向使用者發起訂閱通知的權限,同時此方法也會回傳一個Promise。

其中在pushManager.subscribe中的兩個參數,分別為:

userVisibleOnly : 表示每次收到推送時顯示通知,通常設置為 true。

applicationServerKey : 為 server 端所提供的公鑰,主要用來生成 subscription 資訊,而在server端 的 私鑰 主要功用為Push

const subscribeUser= (swReg)=>{

  const applicationServerKey = urlB64ToUint8Array(publicVapidKey);
  
  swReg.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: applicationServerKey
  })
  .then(subscription =>{
      // 訂閱成功
      updateSubscription(subscription)
  })
  .catch((err)=>{
    console.log('訂閱失敗: ', err);
    
  });
}

如訂閱成功,向 Sever 發送訂閱訊息

const updateSubscription = (subscription) => {
  console.log(subscription);
  fetch('/subscribe', {
    method: 'POST',
    body: JSON.stringify(subscription),
    headers: {
      "content-type": 'application/json'
    }
  }).catch((err) => { console.log(err); })
  
}

此時server端會接收到 subscription的內容,大概像下方這樣

{
  endpoint: '.....',
  keys: {
    auth: '.....',
    p256dh: '.....'
  }
};

server 發送推播訊息

server端接收到 subscription 資訊後,就可以推播訊息給使用者

這邊 我們 用node.js來模擬server端可能運行的方式,如有不全的地方請見諒

app.post('/subscribe', (req, res)=> {

  //取得 subscription 資訊
  
  const subscription = req.body;

  res.status(200).json({});

  //推播內容
  const payload = JSON.stringify({ title: "大俠愛吃漢堡飽" });

  // push 給推播內容
  webpush
  .sendNotification(subscription, payload)
  .catch(err => console.error('rrrrrrrr:'))
  
})

接收推播訊息

最後,當server端推播訊息到Browser端時,背後運行的 Service Worker 會觸發 Push 事件,此時可以透過 registration.showNotification來顯示通知。

self.addEventListener("push", e => {
  console.log('notification is success!!');
  const data = e.data.json();
  
  event.waitUntil(
    self.registration.showNotification(data.title, {
    body: "訂閱成功!",
    icon: "http://pic.616pic.com/ys_b_img/00/44/76/JNaUexjx51.jpg",
    data: {
      dateOfArrival: Date.now(),
      primaryKey: 1
    }
  });
  );

});

咦? 那可以做到 點擊通知訊息導向到指定頁面嗎?

可以的,可以透過notificationclick'來監聽被點擊事件,clients.openWindow為新增一個頁面。

self.addEventListener('notificationclick', e=> {
  const notification = e.notification;
  const primaryKey = notification.data.primaryKey;
  const action = e.action;

  if (action === 'close') {
     //點擊關閉則關閉
    notification.close();
  } else {
   //點擊其他地方打開指定連結 clients.openWindow(url);
    notification.close();
  }
});

到這裡就完成一個Service Worker的 訂閱推播了(呼 壓線了

以上就是關於 Service Worker 常見功能 訂閱推播 實作介紹(呼,而在下一篇文章將回歸原本的主題 Chrome Extension 接下去後續的介紹。

那今天文章先到這邊了,謝謝願意花時間看此篇文章的你,如果文章有錯誤的地方,再麻煩不吝嗇的給予指教,感謝!!

今日有感而發:
記得去年這時候,第一次參加鐵人賽,每天都好焦慮
害怕錯誤、擔心敘述、操心沒必要的操心 ,

而今年,我還是一樣,只是擔心的東西不同了
因為我擔心我的梗圖無法在對的地方登場,你說奇怪不奇怪,原來 我又進步了
今天想分享一首 -> 思念是一種病


上一篇
# 你知道這是什麼嗎? Chrome extension MV3 With Vite - Day7 Service Worker 離線快取
下一篇
你知道這是什麼嗎? Chrome extension MV3 With Vite - Day9 Background 事件監聽器
系列文
你知道這是什麼嗎? Chrome Extension MV3 With Vite30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言